package com.dz.aspect;

import com.dz.annotation.RedisKey;
import com.dz.constant.RabbitMQConstant;
import com.dz.enumeration.AppHttpCodeEnum;
import com.dz.exception.SystemException;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.Objects;

/**
 * @author 鄧浩奇
 * @classname RedisConsistency
 * @description
 * @since 2024/1/21 16:09
 **/

@Component
@Aspect
@Slf4j
public class RedisConsistency {

    private final RabbitTemplate rabbitTemplate;

    @Autowired
    public RedisConsistency(RabbitTemplate rabbitTemplate) {
        this.rabbitTemplate = rabbitTemplate;
    }

    @PostConstruct
    public void init() {
        log.info("RedisConsistency aspect is initialized.");
    }


    // 定义切点
    @Pointcut("execution(* com.dz.service.impl..*(@com.dz.annotation.RedisKey (*),..))")
    public void redisConsistency() {
    }

    // 后置通知
    @After("redisConsistency()")
    public void before(JoinPoint point) {
        log.info("Redis数据一致性前置通知");
        // 拿到被注解标识的参数
        Object args = this.getArgs(point);
        // 发送RabbitMQ消息
        if (Objects.isNull(args)) {
            log.error("Redis parameter error");
            throw new SystemException(AppHttpCodeEnum.PARAMS_ERROR);
        }
        rabbitTemplate.convertAndSend(RabbitMQConstant.SKY_EXCHANGE,RabbitMQConstant.SKY_Long_ROUTING_KEY,args);

        // 根据参数拿到redisKey


    }

    private Object getArgs(JoinPoint point) {
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();
        // 获取方法参数
        Parameter[] parameters = method.getParameters();
        for (int i = 0; i < parameters.length; i++) {
            // 检查参数上是否有RedisKey注解
            if (parameters[i].isAnnotationPresent(RedisKey.class)) {
                // 获取注解实例
                RedisKey annotation = parameters[i].getAnnotation(RedisKey.class);
               return point.getArgs()[i];

            }
        }
        return null;
    }

}
